/**
 * 测试 collection 操作性能
 */
import { OrderedMap, OrderedSet } from 'immutable'
import { run, repeatRun, random } from '../utils'

/**
 * 把匹配 key 的和不匹配 key 的拆分成两部分
 *
 * 结论：
 * 1. 有明确 key，且数量远小于总数据量的情况下，遍历 key 来筛选数据比遍历数据快
 * 2. 构建 OrderedMap() 很慢，非必要不要重新构建 OrderedMap，尽量改为在原 OrderedMap 基础上修改
 */
export function partitionByKey() {
  const entries: [string, number][] = []
  while (entries.length < 1000000) entries.push([`key-${entries.length + 1}`, entries.length + 1])
  const map = OrderedMap(entries)

  let filterKeys = OrderedSet<string>()
  while (filterKeys.size < 5000) filterKeys = filterKeys.add(`key-${random(1, 100000)}`)

  console.log('entries', entries)
  console.log('filterKeys', filterKeys)

  // 1.9秒
  run('OrderedMap partition by key', () => {
    const result = map.partition((v, k) => filterKeys.has(k))
    console.log(result)
  })

  // 50毫秒
  run('OrderedMap delete and pick', () => {
    const notMatch = map.deleteAll(filterKeys)
    const match = OrderedMap(filterKeys.map(key => [key, map.get(key)]))
    console.log([notMatch, match])
  })

  // 200毫秒
  run('遍历（生成数组）', () => {
    const notMatch: [string, number][] = []
    const match: [string, number][] = []
    for (const [key, value] of map) {
      if (filterKeys.has(key)) match.push([key, value])
      else notMatch.push([key, value])
    }
    console.log([notMatch, match])
  })

  // 1.5秒
  run('遍历（生成 OrderedMap）', () => {
    const notMatch: [string, number][] = []
    const match: [string, number][] = []
    for (const [key, value] of map) {
      if (filterKeys.has(key)) match.push([key, value])
      else notMatch.push([key, value])
    }
    const notMatchMap = OrderedMap(notMatch)
    const matchMap = OrderedMap(match)
    console.log([notMatchMap, matchMap])
  })
}

/**
 * 测试 OrderedMap 各类操作的性能
 */
export function orderedMap() {
  const itemsLen = 1000 * 1000
  const entries: [string, number][] = []
  while (entries.length < itemsLen) entries.push([`key-${entries.length + 1}`, entries.length + 1])
  const map = OrderedMap(entries)

  // 90毫秒
  repeatRun('创建 map', () => OrderedMap(entries))
  // 140毫秒
  repeatRun('map 添加 item', () => {
    let map = OrderedMap<string, number>()
    entries.forEach(([key, value]) => {
      map = map.set(key, value)
    })
  })
  // 70毫秒
  repeatRun('map 添加 item（mutable）', () => {
    OrderedMap<string, number>().withMutations(map => {
      entries.forEach(([key, value]) => map.set(key, value))
    })
  })

  // 45ms
  repeatRun('make array', () => [...entries])
  // 120ms
  repeatRun('map make array', () => [...map])
  // 60ms
  repeatRun('map to array', () => map.toArray())

  // 15ms
  repeatRun('array.every()', () => void entries.every(v => v[1] < 9999999))
  // 55ms
  repeatRun('map.every()', () => void map.every(v => v < 9999999))

  // 30ms
  repeatRun('array.sort()', () => entries.sort((a, b) => b[1] - a[1]))
  // 1s
  repeatRun('map.sort()', () => map.sort((a, b) => b - a))
  // 1s
  repeatRun('array.sort and make map', () => OrderedMap(map.toArray().sort((a, b) => b[1] - a[1])))
}

export function array() {
  const array1: number[] = []
  while (array1.length < 10) array1.push(array1.length + 1)
  const array2 = [...array1]
  let match: boolean | undefined

  // total: 5ms
  repeatRun(
    'array compare',
    () => {
      match =
        array1.length === array2.length && array1.every((value, index) => value === array2[index])
    },
    10000,
  )
  console.log('match', match)
}
